/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

import process from 'process';

import { DAEMON_PROCESS_ACTIVE_MAX_LIMIT } from '../const/daemon-const.js';
import { HvigorDaemonClientLogger } from '../log/hvigor-daemon-client-log.js';
import { isHvigorDaemonProcess } from '../util/process-info-util.js';

import { DaemonInfo, DaemonState } from './daemon-info.js';
import { DefaultDaemonRegistry } from './default-daemon-registry.js';

const _log = HvigorDaemonClientLogger.getLogger('daemon-client');

class DaemonClientRegistry extends DefaultDaemonRegistry {
  constructor() {
    super(_log);
  }

  updateDaemonProcessState(daemonInfo: DaemonInfo, daemonState: DaemonState, stateChangeInfo?: string): void {
    const newDaemonInfo = {
      ...daemonInfo,
      state: daemonState,
      info: stateChangeInfo,
    };
    _log.debug(`hvigor client: Update daemon info in registry. daemonInfo=${JSON.stringify(newDaemonInfo)}`);
    this.setInfo(daemonInfo.keyId, newDaemonInfo);

    this.executeAfterChangeProcessStateInClient(daemonInfo, daemonState);
  }

  executeAfterChangeProcessStateInClient(daemonInfo: DaemonInfo, daemonState: DaemonState) {
    switch (daemonState) {
      case DaemonState.IDLE:
        break;
      case DaemonState.HALF_BUSY:
        break;
      case DaemonState.CANCELED:
        break;
      case DaemonState.BUSY:
        break;
      case DaemonState.STOP_REQ:
        break;
      case DaemonState.BROKEN: // Go through
      case DaemonState.STOPPED:
        // 此处区别于server中的改变daemon信息状态后直接调用process.exit(),
        // 因为这里是运行在client中,需要通过发送信号给对应pid的daemon process
        if (isHvigorDaemonProcess(daemonInfo.pid)) {
          process.kill(daemonInfo.pid, 'SIGTERM');
          _log.debug(`hvigor client: Send a 'SIGTERM' signal to daemon process. pid=${daemonInfo.pid}`);
        } else {
          _log.debug(`hvigor client: Process is not a hvigor daemon or not exist. pid=${daemonInfo.pid}`);
        }
        break;
      default:
        throw new Error('hvigor client: Daemon state transition error.');
    }
  }

  /**
   * 先根据工程路径找对应的注册表中是否有对应的信息
   *
   * @returns {DaemonInfo | undefined}
   */
  findProjectDaemon(): DaemonInfo | undefined {
    const cwdPath = process.cwd();
    return this.getAlive()
      .filter((daemonInfo) => {
        return daemonInfo.cwdPath === cwdPath;
      })
      .pop();
  }

  /**
   * 注册表中可用状态的daemon是否超过上限
   *
   * @returns {boolean}
   */
  isAvailableDaemonOverLimit(): boolean {
    const filterResult = this.getInfos().filter((daemonInfo) => {
      return daemonInfo.state !== DaemonState.STOPPED && daemonInfo.state !== DaemonState.BROKEN;
    });

    return filterResult.length === DAEMON_PROCESS_ACTIVE_MAX_LIMIT;
  }

  /**
   * 找一个最久未使用的Idle状态的Daemon process
   *
   * @returns {DaemonInfo | undefined}
   */
  findIdleDaemonWithLRU(): DaemonInfo | undefined {
    const idles = this.getIdles();

    // 没有idle状态的daemon process
    if (idles.length === 0) {
      _log.debug('hvigor client: Cannot find an idle daemon process.');
      return undefined;
    }

    idles.sort((a, b) => {
      return a.lastUsedTime - b.lastUsedTime;
    });

    return idles[0];
  }
}

export const defaultDaemonClientRegistry = new DaemonClientRegistry();
